import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
from tkinter import messagebox
import pandas as pd
import moviepy.editor as mp
from .utils.video_utils import preview_pygame_clip
from concurrent.futures import ThreadPoolExecutor


class Window(tk.Tk):

    def __init__(self) -> None:
        super().__init__()
        self.geometry("800x600+100+100")
        # self.geometry(str(self.sendLabelFrame_width+self.recvLabelFrame_width) + 'x' +
        #   str(self.sendLabelFrame_height + self.recvLabelFrame_height) + "+200+200")
        self.title('工时视频查看器')

        self.tabControlInit()

        # 线程池，用于播放视频，避免阻塞主线程，只能同时播放一个视频,pygame只能是单窗口模式
        self.player_pool = ThreadPoolExecutor(max_workers=1)

    def tabControlInit(self):
        self.tabcontrol = ttk.Notebook(self)
        self.tabcontrol.grid(row=1, columnspan=5, sticky="nw")
        self.manualTab = tk.Frame(self.tabcontrol)
        self.modelTab = tk.Frame(self.tabcontrol)
        self.unitTab = tk.Frame(self.tabcontrol)
        self.autoUnitTab = tk.Frame(self.tabcontrol)

        self.tabcontrol.add(self.manualTab, text="手动选择")
        # self.tabcontrol.add(self.modelTab, text="模块测试库")
        # self.tabcontrol.add(self.unitTab, text="单元测试库")
        # self.tabcontrol.add(self.autoUnitTab, text="自动测试库")

        self.manualTabInit()
        # self.modelTabInit()
        # self.unitTabInit()
        # self.autoUnitTabInit()

    def manualTabInit(self):
        self.manualTabViewInit()

    def manualTabViewInit(self):
        self.labelFrame01 = tk.LabelFrame(
            self.manualTab, text='选择文件')
        self.labelFrame01.grid(row=1, column=1)
        self.labelFrame01_viewInit()

        self.labelFrame02 = tk.LabelFrame(self.manualTab, text="操作")
        self.labelFrame02.grid(row=2, column=1)
        self.labelFrame02_viewInit()

        self.labelFrame03 = tk.LabelFrame(
            self.manualTab, text="视频查看器软件操作说明")
        self.labelFrame03.grid(row=3, column=1)
        self.labelFrame03_viewInit()

    def labelFrame01_viewInit(self):
        if 1:
            # 视频路径选择
            self.videoPath = tk.Label(self.labelFrame01, text="视频路径")
            self.videoPath.grid(row=1, column=1)
            self.videoPath_input = tk.StringVar()
            self.videoPath_entry = tk.Entry(
                self.labelFrame01, width=80, textvariable=self.videoPath_input, state=tk.DISABLED)
            self.videoPath_entry.grid(row=1, column=2)
            self.video_btn_open = tk.Button(
                self.labelFrame01, text="浏览", command=self.select_videoPath)
            self.video_btn_open.grid(row=1, column=3)
        if 1:
            self.excelPath = tk.Label(self.labelFrame01, text="excel文件路径")
            self.excelPath.grid(row=2, column=1)
            self.excelPath_input = tk.StringVar()
            self.excelPath_entry = tk.Entry(
                self.labelFrame01, width=80, textvariable=self.excelPath_input, state=tk.DISABLED)
            self.excelPath_entry.grid(row=2, column=2)
            self.excel_btn_open = tk.Button(
                self.labelFrame01, text="浏览", command=self.select_excelPath)
            self.excel_btn_open.grid(row=2, column=3)

    def labelFrame02_viewInit(self):
        if 0:
            self.loadVideo_btn = tk.Button(
                self.labelFrame02, text="加载视频", command=self.loadVideo)
            self.loadVideo_btn.grid(row=1, column=1)
            self.loadExcel_btn = tk.Button(
                self.labelFrame02, text="加载excel", command=self.loadExcel)
            self.loadExcel_btn.grid(row=1, column=2)
        self.analysis_btn = tk.Button(
            self.labelFrame02, text="同步查看", command=self.analysis_view)
        self.analysis_btn.grid(row=1, column=3)
        pass

    def labelFrame03_viewInit(self):
        helpText_scrollbar = ttk.Scrollbar(self.labelFrame03)
        self.helpText = tk.Text(self.labelFrame03, height=30, width=80)
        helpText_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.helpText.pack(side=tk.LEFT, fill=tk.Y)
        helpText_scrollbar.config(command=self.helpText.yview)
        self.helpText.config(yscrollcommand=helpText_scrollbar.set)

        helpDoc = '''
一、软件说明：
1.1. 软件用于快速查看工时拆解视频的片段，提高效率
1.2. 原理是根据拆解的excel表格中的【开始时间点】【结束时间点】，这两列的数字，自动截取相应的视频片段播放出来
1.3. 【开始时间点】和【结束时间点】，格式应该是视频的绝对秒数，数字格式，比如1分23秒，要写成83
1.4. 时间段是左闭右开区间，包含开头的秒数，不包含结束的秒数，所以上一行的结束描述应该和下一行开始时间相同，避免视频截取有遗漏

二、操作说明：
2.1 在选择文件分别选择 视频路径 和 excel文件路径 的 【浏览】按钮，选择正确的文件
2.2 点击【同步查看】按钮
2.3 在弹出的窗口，下部和右部有滚动条，可以通过滚动条，查看更多未展示数据
2.4 视频查看有两种模式，快速预览，详细查看
2.4.1 快速预览模式：3倍速度播放片段，可以双击某行或者选中某行后单击下面的【快速预览】按钮
2.4.2 详细查看模式：正常倍速播放片段，选中某行，点击下面的【详细查看】按钮

三、信息反馈：
使用过程中可反馈信息给作者华昌
手机号: 13430388853(微信同号)

四、更新时间
------2024-05-06 v0.0.1
1. 增加了视频的暂停功能，空格键 或者 点击视频
2. 增加了导入文件错误的提示功能
------2024-05-05

'''
        self.helpText.insert(tk.END, helpDoc)

    def loadVideo(self):
        try:
            self.VIDEO = mp.VideoFileClip(self.videoPath_input.get())
            duration = self.VIDEO.duration
            name = self.VIDEO.filename
            fps = self.VIDEO.fps

            messagebox.showinfo('Info', f'分析视频【{name}】加载完成,时长{
                                duration}, fps{fps}')
        except Exception as e:
            messagebox.showwarning('Warn', f'加载视频出错了:{e}')

    def loadExcel(self):
        try:
            self.excel_df = pd.read_excel(self.excelPath_input.get())
            messagebox.showinfo('Info', '分析数据excel加载完成')

        except Exception as e:
            messagebox.showwarning('Warn', f'加载excel表格出错了:{e}')

    def analysis_view(self):
        # 初始化表格窗口treeview

        # 列数据转换
        df_columns = list(self.excel_df.columns.values)

        self.treeTop = tk.Toplevel(self)
        self.treeTop.geometry("800x480+200+100")

        # 创建treeview
        self.excel_treeview = ttk.Treeview(
            self.treeTop, columns=df_columns, show='headings', selectmode='browse')

        # 创建滚动条
        self.scrollBar_y = ttk.Scrollbar(
            self.treeTop, orient=tk.VERTICAL, command=self.excel_treeview.yview)
        self.scrollBar_x = ttk.Scrollbar(
            self.treeTop, orient=tk.HORIZONTAL, command=self.excel_treeview.xview)

        # 绑定滚动条
        self.excel_treeview.configure(yscrollcommand=self.scrollBar_y.set)
        self.excel_treeview.configure(xscrollcommand=self.scrollBar_x.set)

        self.scrollBar_y.pack(side=tk.RIGHT, fill=tk.Y)
        self.scrollBar_x.pack(side=tk.BOTTOM, fill=tk.X)
        self.excel_treeview.pack(expand=True, side=tk.TOP, fill=tk.BOTH)

        # 设置列
        for col in df_columns:
            self.excel_treeview.heading(col, text=col)

            if col != "作业内容":
                self.excel_treeview.column(col, width=100, anchor="center")
            else:
                self.excel_treeview.column(col, width=150, anchor="w")

        # 导入数据
        for index, row in self.excel_df.iterrows():
            self.excel_treeview.insert("", "end", values=row.tolist())
            pass

        # 增加操作按钮
        self.excel_treeview_option()

        # 注册事件回调函数
        self.excel_treeview_callback()

    def excel_treeview_callback(self):
        # 注册点击事件回调函数
        # def treeviewClick(event):
        #     for item in self.excel_treeview.selection():
        #         item_text = self.excel_treeview.item(item, "values")
        #         print(item_text)

        # 鼠标左键抬起
        # self.treeTop.bind("<ButtonRelease-1>", treeviewClick)

        def doubleClick(event):
            '''
                双击当前row，进行预览视频片段
            '''
            # 获取当前点击的组件，treeview
            # e = event.widget
            # 第一个参数可选'item','row', 'column'，分别对应的内容
            # iid 是item的唯一标识iid值，不是item本身的字典
            # iid = e.identify('item', event.x, event.y)
            # print(iid)
            # print(e.item(iid))
            self.excel_treeview_clip_preview()
        self.excel_treeview.bind("<Double-1>", doubleClick)

    def excel_treeview_option(self):
        self.treeTop_frame02 = tk.LabelFrame(self.treeTop)
        self.treeTop_frame02.pack(side=tk.BOTTOM, fill=tk.X)
        self.play_btn = tk.Button(
            self.treeTop_frame02, text='快速预览', command=self.excel_treeview_clip_preview)
        self.play_btn.grid(row=1, column=1)
        self.play_btn = tk.Button(
            self.treeTop_frame02, text='详细查看', command=self.excel_treeview_clip_play)
        self.play_btn.grid(row=1, column=2)
        pass

    def select_videoPath(self):
        # [ ] filetypes 属性使用
        filename = askopenfilename()
        if filename:
            self.videoPath_input.set(filename)
            self.loadVideo()
        else:
            messagebox.showwarning('警告', '未正确选择视频文件')

    def select_excelPath(self):
        # [ ] filetypes 属性使用
        filename = askopenfilename()
        if filename:
            self.excelPath_input.set(filename)
            self.loadExcel()
        else:
            messagebox.showwarning('警告', '未正确选择工时分析excel文件')

    def test(self):
        self.btn_play = tk.Button(self.manualTab, text="播放", command=self.play)
        self.btn_play.pack()
        self.btn_pause = tk.Button(
            self.manualTab, text="暂停", command=self.pause)
        self.btn_pause.pack()
        self.btn_stop = tk.Button(self.manualTab, text="停止", command=self.stop)
        self.btn_stop.pack()

    def excel_treeview_item_getDuration(self):
        foc = self.excel_treeview.focus()
        row_data = self.excel_treeview.set(foc)

        # [x] 后续增加异常处理
        try:
            start_t = int(row_data['开始时间点'])
            end_t = int(row_data['结束时间点'])
        except:
            messagebox.showwarning('警告', '未正确获取开始和结束时间点')
            return None

        if start_t >= end_t:
            messagebox.showwarning(
                '警告', f'开始时间点{start_t},结束时间点{end_t},时间差异常...')
            return None
        else:
            return start_t, end_t

    def excel_treeview_clip_preview(self):
        time_duration = self.excel_treeview_item_getDuration()
        if time_duration is None:
            return
        else:
            start_t, end_t = time_duration
        # 获取视频片段
        video_clip = self.VIDEO.subclip(start_t, end_t)
        # 快速预览
        def player(): return preview_pygame_clip(video_clip, times=3)
        self.player_pool.submit(player)

    def excel_treeview_clip_play(self):
        time_duration = self.excel_treeview_item_getDuration()
        if time_duration is None:
            return
        else:
            start_t, end_t = time_duration
        # 获取视频片段
        video_clip = self.VIDEO.subclip(start_t, end_t)
        # 快速预览
        def player(): return preview_pygame_clip(video_clip, times=1)
        self.player_pool.submit(player)


def main():
    demo = Window()
    demo.mainloop()


if __name__ == '__main__':
    main()
